package com.sanshengshui.netty.server;

import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.SimpleChannelInboundHandler;
import java.net.InetAddress;
import java.util.Date;

/**
 * @Sharable 是 Netty 提供的注解，用于标识该处理器是可共享的。这意味着同一个处理器实例可以被多个通道共享，而无需创建多个实例。
 */
@Sharable
public class ServerHandler extends SimpleChannelInboundHandler<String> {
    /**
     * 当新的连接被建立时，channelActive 方法会被调用。在这里，它向客户端发送欢迎消息，包括主机名和当前时间。
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        // 为新连接发送庆祝
        ctx.write("Welcome to " + InetAddress.getLocalHost().getHostName() + "!\r\n");
        ctx.write("It is " + new Date() + " now.\r\n");
        ctx.flush();
    }

    /**
     * channelRead0 方法在收到客户端消息时被调用。根据客户端的请求内容，它生成一个相应的消息，
     * 并通过通道的 write 方法写入。如果客户端请求关闭连接（例如发送"bye"），则通过监听器（ChannelFutureListener）设置关闭连接。
     * @param ctx
     * @param request
     * @throws Exception
     */
    @Override
    public void channelRead0(ChannelHandlerContext ctx, String request) throws Exception {
        // Generate and write a response.
        String response;
        boolean close = false;
        if (request.isEmpty()) {
            response = "Please type something.\r\n";
        } else if ("bye".equals(request.toLowerCase())) {
            response = "Have a good day!\r\n";
            close = true;
        } else {
            response = "Did you say '" + request + "'?\r\n";
        }

        ChannelFuture future = ctx.write(response);

        if (close) {
            future.addListener(ChannelFutureListener.CLOSE);
        }
    }

    /**
     * channelReadComplete 方法在通道读取操作完成时被调用，它通过 ctx.flush() 确保所有写入操作都被刷新到远程节点。
     * @param ctx
     */
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) {
        ctx.flush();
    }

    /**
     * exceptionCaught 方法在处理过程中发生异常时被调用。在这里，它打印异常的堆栈轨迹，并关闭相关的通道。
     * @param ctx
     * @param cause
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        cause.printStackTrace();
        ctx.close();
    }
}
/**
 * 总体而言，这个服务器处理器类负责处理新连接的激活、读取客户端的请求、生成相应的响应以及处理异常。这个例子中的业务逻辑比较简单，根据客户端的输入作出相应的回应。
 */
